package com.bsoft.service.impl;

import cn.hutool.core.util.NumberUtil;
import com.bsoft.Exception.CommonException;
import com.bsoft.event.NoticeEvent;
import com.bsoft.mapper.business.RegisterMapper;
import com.bsoft.service.RegisterService;

import com.bsoft.utils.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.apache.logging.log4j.spi.LoggerRegistry;
import org.dom4j.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.Arrays.asList;

/**
 * 挂号实现类
 *
 * @author liujx
 * @date 2019/7/2
 */
@Service
public class RegisterServiceImpl extends ConmonUtil implements RegisterService {

    private static Logger logger = LoggerFactory.getLogger(RegisterServiceImpl.class);
    @Resource
    private RegisterMapper registerMapper;

    @Value("${pjHttp}")
    private String pjHttp;

    @Value("${wechatSendMsgUrl}")
    private String wechatSendMsgUrl;

    @Value("${hospitalId}")
    private String hospitalId;

    @Value("${zhxyfSettPrePushUrl}")
    private String zhxyfSettPrePushUrl;

    /**
     * 门诊挂号电子票据上传
     */
    @Override
    public void invEBillRegistration() {

        List<Map<String, Object>> regList = registerMapper.InvEBillRegistration();

        logger.info("门诊挂号上传开始" + regList.size());
        if (regList.size() > 0) {
            for (Map<String, Object> map : regList) {
                List<Map<String, Object>> payChannelDetailList = new ArrayList<>();
                List<Map<String, Object>> chargeDetailList = new ArrayList<>();
                List<Map<String, Object>> listDetailList = new ArrayList<>();
                List<Map<String, Object>> otherInfoList = new ArrayList<>();
                List<Map<String, Object>> emptyList = new ArrayList<>();
                List<Map<String, Object>> payChannelGHYB = new ArrayList<>();
                List<Map<String, Object>> payChannelGH = new ArrayList<>();

                payChannelGH = registerMapper.getPayChannelDetailList_gh(map);

                payChannelGHYB = registerMapper.getPayChannelDetailList_mzyb(map);

                chargeDetailList = registerMapper.getChargeDetailList_gh(map);
                listDetailList = registerMapper.getListDetailList_gh(map);
                otherInfoList = registerMapper.getOtherInfoList_gh(map);

                payChannelDetailList.addAll(payChannelGH);
                if (!CollectionUtils.isEmpty(payChannelGHYB)) payChannelDetailList.addAll(payChannelGHYB);


                map.put("payChannelDetail", payChannelDetailList);//交费渠道列表
                map.put("chargeDetail", chargeDetailList);// 收费项目明细
                map.put("listDetail", listDetailList);//清单项目明细
                map.put("otherInfo", otherInfoList);//其它扩展信息列表
                map.put("otherMedicalList", emptyList);//其它支付信息列表
                map.put("payOrderInfo", emptyList);//其它医保信息列表

                try {
                    httpUpdate("invEBillRegistration", map);
                } catch (Exception e) {
                    e.printStackTrace();
                    logger.error("调用电子票据失败::" + e);
                }
            }
        }
    }

    /**
     * 门诊收费电子票据上传
     */
    @Override
    public void invoiceEBillOutpatient() {
        List<Map<String, Object>> outList = registerMapper.InvoiceEBillOutpatient();

        logger.info("门诊缴费上传开始" + outList.size());

        if (outList.size() > 0) {
            for (Map<String, Object> map : outList) {
                List<Map<String, Object>> payChannelDetailList = new ArrayList<>();
                List<Map<String, Object>> chargeDetailList = new ArrayList<>();
                List<Map<String, Object>> listDetailList = new ArrayList<>();
                List<Map<String, Object>> otherInfoList = new ArrayList<>();
                List<Map<String, Object>> emptyList = new ArrayList<>();

                List<Map<String, Object>> payChannelMZ = registerMapper.getPayChannelDetailList_mz(map);
                List<Map<String, Object>> payChannelMZYB = registerMapper.getPayChannelDetailList_mzyb(map);
                payChannelDetailList.addAll(payChannelMZ);
                if (!CollectionUtils.isEmpty(payChannelMZYB)) payChannelDetailList.addAll(payChannelMZYB);


                chargeDetailList = registerMapper.getChargeDetailList_mz(map);
                listDetailList = registerMapper.getListDetailList_mz(map);
                otherInfoList = registerMapper.getOtherInfoList_mz(map);


                map.put("payChannelDetail", payChannelDetailList);//交费渠道列表
                map.put("chargeDetail", chargeDetailList);// 收费项目明细
                map.put("listDetail", listDetailList);//清单项目明细
                map.put("otherInfo", otherInfoList);//其它扩展信息列表
                map.put("otherMedicalList", emptyList);//其它支付信息列表
                map.put("payOrderInfo", emptyList);//其它医保信息列表

                try {
                    httpUpdate("invoiceEBillOutpatient", map);
                } catch (Exception e) {
                    e.printStackTrace();
                    logger.error("调用电子票据失败::" + e);
                }
            }
        }

    }

    /**
     * 住院电子票据上传
     */
    @Override
    public void invEBillHospitalized() {
        List<Map<String, Object>> outList = registerMapper.InvEBillHospitalized();

        logger.info("住院缴费上传开始" + outList.size());

        if (outList.size() > 0) {
            for (Map<String, Object> map : outList) {
                List<Map<String, Object>> payChannelDetailList = new ArrayList<>();
                List<Map<String, Object>> chargeDetailList = new ArrayList<>();
                List<Map<String, Object>> listDetailList = new ArrayList<>();
                List<Map<String, Object>> otherInfoList = new ArrayList<>();
                List<Map<String, Object>> payMentVoucherList = new ArrayList<>();
                List<Map<String, Object>> emptyList = new ArrayList<>();

                payChannelDetailList = registerMapper.getPayChannelDetailList_zy(map);
                chargeDetailList = registerMapper.getChargeDetailList_zy(map);
                listDetailList = registerMapper.getListDetailList_zy(map);
                otherInfoList = registerMapper.getOtherInfoList_zy(map);
//                otherInfoList = registerMapper.getPayMentVoucherList_zy(map);

                map.put("payChannelDetail", payChannelDetailList);//交费渠道列表
                map.put("chargeDetail", chargeDetailList);// 收费项目明细
                map.put("listDetail", listDetailList);//清单项目明细
                map.put("otherInfo", otherInfoList);//其它扩展信息列表
                map.put("otherMedicalList", emptyList);//其它支付信息列表
                map.put("payOrderInfo", emptyList);//其它医保信息列表
                map.put("payMentVoucher", payMentVoucherList);//预交金凭证消费扣款列表

                try {
                    httpUpdate("invEBillHospitalized", map);
                } catch (Exception e) {
                    e.printStackTrace();
                    logger.error("调用电子票据失败::" + e);
                }
            }
        }

    }

    public String httpUpdate(String action, Map<String, Object> map) throws Exception {
        String resultString = null;
        String map2Json = JSONUtil.map2Json(map);
//        logger.info(action + "上传数据:" + (map2Json.length() > 200 ? map2Json.substring(0, 200) : map2Json));
        logger.error(action + "上传数据:" + map2Json);
        resultString = HttpClientUtil.doPostJsonPj1(pjHttp + "/electronic/" + action + "All", map2Json, hospitalId);
        logger.error(action + "返回数据:" + resultString);

        return resultString;
    }


    /**
     * 挂号电子票据冲红
     */
    @Override
    public void registerETicketRed() {


        List<Map<String, Object>> writeOffEBillList = registerMapper.writeOffEBill();
        logger.error("挂号票据冲红开始:writeOffEBill,视图:registerTicketFlushRed,冲红数据量:" + writeOffEBillList.size());
        for (Map<String, Object> writeOffEBill : writeOffEBillList) {

            Map<String, Object> map = new HashMap<>();
            map.put("billBatchCode", writeOffEBill.get("billBatchCode"));
            map.put("billNo", writeOffEBill.get("billNo"));
            map.put("reason", writeOffEBill.get("reason"));
            map.put("operator", writeOffEBill.get("operator"));
            map.put("busDateTime", writeOffEBill.get("busDateTime"));
            map.put("placeCode", writeOffEBill.get("placeCode"));

            String res = "";
            try {
                res = httpUpdate("writeOffEBill", map);
                //解析结果回写数据
                if (Double.valueOf(JSONUtil.toHashMap(res).get("code").toString()).equals(200.0)) {
                    registerMapper.udaptePjztZf(writeOffEBill.get("SBXH").toString());
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("调用电子票据失败::" + e);
            }
        }
    }

    /*{
    "templateType": 1,
    "idCard": "510105198801283017",
    "patId": 0,
    "visitCardNo": "",
    "first": "咨询提醒",
    "url": "https://mkxmjk.mcdex.cn/wechat/createcode?c=668&m=0&v=0&p=54&a=19880128&N=刘**&d=|33|丁桂活络膏(乙)|410|外用|10.0000张|qd|1/1&k=&t=1515120166145582",
    "keywords": {
        "keyword1": "请查看您的用药指导。",
        "keyword2": "20240417",
        "keyword3": "",
        "keyword4": "",
        "keyword5": ""
    }
}*/

    /**
     * 省骨科合理用药推送微信
     */
    @Override
    public void medicationPush_Wechat() {
        String sysTime = new SimpleDateFormat("yyyyMMdd").format(new Date());

        List<Map<String, Object>> medicationPushList = registerMapper.medicationPushList();

        for (Map<String, Object> medicationPushMap : medicationPushList) {
            Map<Object, Object> keywordsPar = new HashMap<>();
            keywordsPar.put("keyword1", "请查看您的用药指导。");
            keywordsPar.put("keyword2", sysTime);
            keywordsPar.put("keyword3", "");
            keywordsPar.put("keyword4", "");
            keywordsPar.put("keyword5", "");
            medicationPushMap.put("keywords", keywordsPar);

            try {
                String jsonStr = JSONUtil.map2Json(medicationPushMap);
                logger.error("用药推送入参:" + jsonStr);
                String res = WebServiceClientUtil.pusPlatform_Customize("wx_message", jsonStr, wechatSendMsgUrl);
                if (StringUtils.isEmpty(res)) {
                    continue;
                }
                String[] resArr = res.split("<return>");
                res = resArr[1];
                resArr = res.split("</return>");
                res = resArr[0];
                logger.error("用药推送出参:" + res);
                Map<String, Object> resMap = JSONUtil.toHashMap(res);

                if ("1.0".equals(resMap.get("code").toString())) {
                    medicationPushMap.put("PUSHSTATUS", "1");
                    medicationPushMap.put("PUSHRESULT", "推送成功");
                } else {
                    medicationPushMap.put("PUSHSTATUS", "2");
                    medicationPushMap.put("PUSHRESULT", "推送失败,可能患者未关注公众号或未在公众号绑卡");
                }
                registerMapper.insetMedicationPushLog(medicationPushMap);
            } catch (Exception e) {
                logger.error("用药推送异常:" + e.getMessage());
                e.printStackTrace();
            }

        }

    }


    @Override
    public void medicineMachinePush_Wechat() {
        String sysTime = new SimpleDateFormat("yyyyMMdd").format(new Date());

        List<Map<String, Object>> medicationPushList = registerMapper.medicationMachinePushList();


        Map<String, Object> tokenMap = new HashMap<>();
        tokenMap.put("Authorization", "Basic QlNPRlQ6QVNQMDAxMg==");
        tokenMap.put("TENANT-CODE", "ASP0012");
        tokenMap.put("body", "");

        String token = "";
        try {
            String bsXml = XmlMapUtils.formatXml(XmlMapUtils.map2xml(tokenMap, "BSXml"));
            //先调用token
            String tokenRes = WebServiceClientUtil.pusPlatform_Customize("mq_token", bsXml, wechatSendMsgUrl);
            if (!StringUtils.isEmpty(tokenRes)) {
                Map<String, Object> restokenMap = WebServiceClientUtil.returnWebServiceStr(tokenRes);
                token = restokenMap.get("access_token").toString();
            }
        } catch (Exception e) {
            logger.error("获取token信息失败:" + e.getMessage());
        }

        String a = "{\n" +
                "      \"aspCode\": \"ASP0012\",\n" +
                "      \"appId\": \"2ch4409edc\",\n" +
                "      \"hospitalCode\": \"213932510107410927\",\n" +
                "      \"medicalCombo\": \"0\",\n" +
                "      \"branchCode\": \"01\",\n" +
                "      \"operatorNo\": \"001\",\n" +
                "      \"terminalId\": \"\",\n" +
                "      \"transactionCode\": \"mq_0001\",\n" +
                "      \"version\": \"\",\n" +
                "      \"needPage\": false,\n" +
                "      \"pageNo\": \"1\",\n" +
                "      \"pageSize\": \"10\"\n" +
                "    }";

        Map<String, Object> params = new HashMap<>();
        Map<String, Object> basic = new HashMap<>();
        Map<String, Object> detail = new HashMap<>();

        JSONObject basicJson = JSONObject.fromObject(a);
        detail.put("msgId", "12343213");
        detail.put("messType", "0");
        detail.put("sendType", "2");
        detail.put("templateId", "Ovblv7abuNDFJPXkSOxTOGot9WrxvGGLB24fkuvB3cA");
        detail.put("content", "药品信息推送（医院名称，拿药地方）");

        params.put("basic", basicJson);
        params.put("detail", detail);


        Map<String, Object> tokenMap1 = new HashMap<>();
        tokenMap1.put("Authorization", "Bearer "+token);
        tokenMap1.put("TENANT-CODE", "ASP0012");
        for (Map<String, Object> medicationPushMap : medicationPushList) {

            Map<Object, Object> parmMap = new HashMap<>();
            Map<Object, Object> keywordsPar = new HashMap<>();
            parmMap.put("first", medicationPushMap.get("first"));
            parmMap.put("idCard", medicationPushMap.get("idCard"));
            parmMap.put("patId", medicationPushMap.get("patId"));
            parmMap.put("remake", medicationPushMap.get("remake"));
            parmMap.put("url", "");
            parmMap.put("visitCardNo", "");

            keywordsPar.put("keyword1", medicationPushMap.get("keyword1"));
            keywordsPar.put("keyword2", medicationPushMap.get("keyword2"));
            keywordsPar.put("keyword3", medicationPushMap.get("keyword3"));
            parmMap.put("keywords", keywordsPar);

            detail.put("param", parmMap);

            try {
                if (ObjectUtils.isEmpty(token)) {
                    logger.info("获取token为空了"+tokenMap1);
                    continue;
                }
                String jsonStr = JSONUtil.map2Json(params);
                logger.error("发药机:药品信息推送推送入参:" + jsonStr);

                tokenMap1.put("body", jsonStr);

                String xmlReq = XmlMapUtils.formatXml(XmlMapUtils.map2xml(tokenMap1, "BSXml"));
                String res = WebServiceClientUtil.pusPlatform_Customize("mq_0001", xmlReq, wechatSendMsgUrl);
                if (StringUtils.isEmpty(res)) {
                    continue;
                }

                Map<String, Object> resMap = WebServiceClientUtil.returnWebServiceStr(res);
                //推送成功后更新推送标志 {"result":{"msg":"推送成功","ext":"","code":1,"data":[]},"status":"T","code":200,"msgCode":null,"msg":null,"exception":null,"responseTime":"1269","inParamSize":"630B","transId":"690afc30e4b09a2c4f7e8683","secret":null,"timeStamp":null}
                logger.error("发药机:是否推送窗口信息成功:" + ("200.0".equals(resMap.get("code").toString())));
                if ("200.0".equals(resMap.get("code").toString())) {
                    registerMapper.updateCFPushFlag(medicationPushMap);
                }

            } catch (Exception e) {
                e.printStackTrace();
                logger.error("发药机:药品信息推送推送异常:" + e.getMessage());
                e.printStackTrace();
            }

        }

    }


    @Override
    public void getClinicalPathwaysExecutionResult() {

        List<Map<String, Object>> getCpResultList = registerMapper.getCpResult();

        String lclj_url = "http://196.168.0.191:8080/DETCP/services/InterfaceForHis?wsdl";
        for (Map<String, Object> map : getCpResultList) {
            try {
                map.put("Method", "GetCpResult");
                map.put("HospitalCode", "0000000000");
                String requst = "<![CDATA[" + XmlMapUtils.formatXml(XmlMapUtils.map2xml(map, "Requst")) + "]]>";
//                String requst = "<![CDATA["+ XmlMapUtils.map2xml(map, "Requst")+"]]>";
//                String requst = "<![CDATA["+  JSONUtil.map2Json(map)+"]]>";

                logger.error("入参:{}", requst);
                String resStr = WebServiceClientUtil.getClinicalPathwaysPt(lclj_url, requst);
                logger.error("调用临床路径执行结果返回[ZYH:" + map.get("PatientID") + "]" + resStr);

                if (!StringUtils.isEmpty(resStr)) {
                    Map<String, Object> resMap = XmlMapUtils.xml2map(resStr, false);
                    if ("1".equals(resMap.get("Return").toString())) {
                        Map<String, Object> lcjgljMap = new HashMap<>();
                        lcjgljMap.put("ZYH", map.get("PatientID"));
                        lcjgljMap.put("SFZXLCLJ", resMap.get("IsCp"));
                        lcjgljMap.put("TCYY", resMap.get("ExitReason"));
                        lcjgljMap.put("SFBY", resMap.containsKey("VariationFlag") ? resMap.get("VariationFlag") : "");
                        lcjgljMap.put("BYYY", resMap.containsKey("VariationContent") ? resMap.get("VariationContent") : "");
                        lcjgljMap.put("BZMC", resMap.containsKey("DiseaseName") ? resMap.get("DiseaseName") : "");
                        registerMapper.save_cp_lcljjg(lcjgljMap);
                    }
                } else {
                    continue;
                }

            } catch (Exception e) {
                logger.error("调用临床路径执行结果异常:", e);
                continue;
            }
        }

    }

    /*智慧西药药房:已缴费处方推送明细:http://196.168.1.93:6868/api/Home/sendToFYS*/
    @Override

    public void zhzyfPush_settPre() {
        //获取当天已经缴费的患者信息
        List<Map<String, Object>> patienInfoList = registerMapper.get_zhzyf_SettPrePatienInfo();
        Map<String, Object> req = new HashMap<>();
        req.put("codekey", "Outpatientorder");
        for (Map<String, Object> patienInfoMap : patienInfoList) {

            try {
                List<Map<String, Object>> settPreDetailList = registerMapper.get_zhzyf_SettPreDetail(patienInfoMap);
                if (CollectionUtils.isEmpty(settPreDetailList)) {
                    logger.error("根据患者档案ID[{}]获取当天的发药处方失败", patienInfoMap.get("BRID"));
                    continue;
                }


                // 使用 Stream 处理并移除指定键
                List<Map<String, Object>> filteredList = settPreDetailList.stream()
                        .map(map -> {
                            // 创建新 Map 避免修改原数据（若需直接修改原 Map，可跳过此步骤）
                            Map<String, Object> newMap = new HashMap<>(map);
                            newMap.remove("FPHM");  // 移除键 "cfsb"
                            newMap.remove("SBXH");  // 移除键 "sbxh"
                            newMap.remove("CFSB");  // 移除键 "sbxh"
                            return newMap;
                        }).collect(Collectors.toList());

                req.put("pharmacy", patienInfoMap.get("YQBS"));
                req.put("data", filteredList);

                ObjectMapper objectMapper = new ObjectMapper();

                String reqStr = objectMapper.writeValueAsString(req);

                logger.info("调用发药机入参:{}", reqStr);
                List<NameValuePair> params = new ArrayList<>();
                params.add(new BasicNameValuePair("strcode", reqStr));

                String res = HttpClientUtil.doPostJsonZhxyf(zhxyfSettPrePushUrl, params);
                logger.info("调用发药机接口返回参数:{}", res);
                if (!StringUtils.isEmpty(res)) {
                    Map<String, Object> resMap = JSONUtil.toHashMap(res);
                    if ("0".equals(resMap.get("code").toString())) {
                        registerMapper.inserZhxyfPushLog(settPreDetailList);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("发药机推送异常:", e);
            }
        }
    }
}

